package es.duma.util.xsl;

import es.duma.util.log.Log;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

/*
 * Lista sincronizada para almacenar las respuestas parciales de cada peticion REST lanzada
 * de manera concurrente (un resultado por hilo).
 */
public class ListaResultados {
    
    /**
     * La lista se basa en un objeto de la clase java.util.Vector 
     */
    private Vector lista;
    
    /**
     * Numero total de elementos de la lista 
     */
    private int total;
    
    /**
     * Numero de elementos alamacenado del total posible
     */
    private int almacenados;
    
    /**
     * Hilos que han terminado la peticion REST
     */
    int hilosTerminados[]; 


    private boolean available = false;


    /**
     * Constructor de la lista sincronizada
     * @param total
     * @param hilosTerminados
     */
    public ListaResultados(int total,int hilosTerminados[]){
        this.total=total;
        this.almacenados=0;
        lista =new Vector(total);
        
        this.hilosTerminados=hilosTerminados;
        Log.debug(this," Se crea la lista compartida de "+lista.size()+" elementos");
    }

    /**
     * Anyade un dato en una derminada posicion de la lista.
     * La lista queda bloqueda de solicitudes get hasta que se rellene por completo (lista llena)
     * @param dato dato a nayadir a la lista
     * @param position
     */
    public synchronized void addDatoSync(Object dato,int position){
        while (available == true) {
            Log.debug(this,"Dentro del while PUT. Hilo "+position);
            try {
                wait();
            } catch (InterruptedException e) {
                Log.error(this,"Error de concurrencia. Hilo "+position+" "+e);
            }
        }
  
        Log.debug(this,"Fuera del while PUT. Hilo "+position);
        try{
            lista.add(dato);
        }catch (Exception e){
            Log.error(this,"Error al anyadir en la lista "+e);
            
        }
        hilosTerminados[0]++;
        Log.debug(this,"Se ha anyadido un resultado en la posicion "+position+" almacenados "+hilosTerminados[0]+ " de "+total+"\n");

        if (hilosTerminados[0]>=(total)){
            Log.debug(this,"Lista llena");
            available=true;
            notifyAll();
            Log.debug(this,"Se envia notify. La lista ya puede ser consumida");            
        }
    }


    /**
     * Se solicita la lista completa para ser consumida.
     * Esta accion queda bloqueada a la espera (wait) hasta que la lista este completa.
     * @return
     */
    public synchronized List getListaSync(){
        while (available == false) {
            Log.debug(this,"Dentro del while GET");
            try {
                Log.debug(this,"Hay que esperar a consumir. La lista aun no esta completa");
                wait();
            } catch (InterruptedException e) {
                Log.error(this,"Error de concurrencia "+e);
            }
        }
        Log.debug(this,"Fuera del while GET");
        available=false;
        notify();
        Log.debug(this,"Puedo consumir"); 
        return lista;
    }
    
}
